import pymysql
import pandas as pd
from zhipuai import ZhipuAI
import inspect
import json

def retrieve_emails(n,user_id="me"):
    """
    获取指定数量的最近邮件
    参数：
    :param n: 要检索的邮件数量，数据格式为int类型
    :param user_id: 要检索的邮件用户的id，默认值是"me",数据格式为字符串类型
    返回：
    一个列表，其中每个元素都是一个字典，表示一封邮件，每个字典包含以下键：
    "from_userid":发件人id。
    "date":邮件发送日期。
    "subject":邮件主题。
    "snippet":邮件的摘要（前100个字符）。
    """

    connection = pymysql.connect(
        host='localhost',  # 数据库地址
        user='root',  # 数据库用户名
        passwd="1qaz2wsx",  # 数据库密码
        db='my_mail',  # 数据库名
        charset='utf8'  # 字符集选择utf8
    )

    sql = f"select * from mailbox where userid = '{user_id}' order by date desc limit {n}"
    try:
        with connection.cursor() as cursor:
            sql_query = sql
            cursor.execute(sql_query)
            results = cursor.fetchall()
    finally:
        cursor.close()

    columns_name = [desc[0] for desc in cursor.description]
    df = pd.DataFrame(results,columns=columns_name)
    print(df)

    return df.to_json(orient="records")

result = retrieve_emails(2)
# print(result)
api_key = "4956db3da95d43eab77efa6937882679.Xm27NhBWZPJE3ORb"
client = ZhipuAI(api_key=api_key)

messages = [{"role":"system","content":"这是我邮箱的最近2封邮件的内容:%s" % result},
            {"role":"system","content":"邮件的内容是从my_mail库的mailbox表中获取的"},
            {"role":"user","content":"请问我的最近2封邮件是谁发送的?都有什么内容?"}]

# response=client.chat.completions.create(model="glm-4",messages=messages)
# print(response.choices[0].message.content)

def auto_functions(function_list):
    """
    chat模型的functions参数编写函数
    :param function_list: 包含一个或多个函数对象的列表
    :return: 满足chat模型的functions参数要求的functions对象
    """
    def function_generator(function_list):
        # 创建空列表，用于保存每个函数的描述字典
        functions = []
        # 对每个外部函数进行循环
        for function in function_list:
            # 读取函数对象的函数说明
            function_description = inspect.getdoc(function)
            # 读取函数的函数名字符串
            function_name = function.__name__
            ## 提示词 one-shot
            system_prompt1 = """
            输出结果必须是一个JSON格式的字典,举个例子：
            [{'type': 'function', 'function': {'name': 'sunwukong_function', 'description': '该函数定义了数据集计算过程，接收一个数据表字符串参数，并返回一个JSON格式的Dataframe类型对象。', 
            'parameters': {'type': 'object', 'properties': {'data': {'type': 'string', 'description': '带入计算的数据表，用字符串进行表示'}},
             'required': ['data'], 'additionalProperties': False}}}]
            """
            system_prompt2 = '以下是某的函数说明：%s,输出结果必须是一个JSON格式的字典，只输出这个字典即可，前后不需要任何前后修饰或说明的语句' % function_description
            user_prompt = '根据这个函数的函数说明，请帮我创建一个JSON格式的字典，这个字典有如下5点要求：\
                                       1.字典总共有三个键值对；\
                                       2.第一个键值对的Key是字符串name，value是该函数的名字：%s，也是字符串；\
                                       3.第二个键值对的Key是字符串description，value是该函数的函数的功能说明，也是字符串；\
                                       4.第三个键值对的Key是字符串parameters，value是一个JSON Schema对象，用于说明该函数的参数输入规范。\
                                       5.输出结果必须是一个JSON格式的字典，只输出这个字典即可，前后不需要任何前后修饰或说明的语句' % function_name
            messages = [{"role":"system","content":system_prompt1},
                        {"role":"system","content":system_prompt2},
                        {"role":"user","content":user_prompt}]
            response = client.chat.completions.create(model="glm-4",messages=messages)
            print(response)
            json_str = response.choices[0].message.content.replace("```json", "").replace("```", "")
            json_function_description = json.loads(json_str)
            json_str = {"type": "function", "function": json_function_description}
            functions.append(json_str)
        return functions

    ## 最大可以尝试4次
    max_attempts = 4
    attempts = 0
    while attempts < max_attempts:
        try:
            functions = function_generator(function_list)
            # 如果代码成功执行，跳出循环
            break
        except Exception as  e:
            attempts += 1
            print("发生错误的原因:",e)
            if attempts == max_attempts:
                print("已达到最大尝试次数，程序终止。")
                raise
            else:
                print("正在重新运行...")
    return functions

function_list = [retrieve_emails]
# functions = auto_functions(function_list)
# print(functions)

def run_conversation(messages,function_list = None,model="glm-4"):
    """
    能够自动执行外部函数的对话模型
    :param messages: 必须参数，字典类型，输入到chat模型的message参数对象
    :param function_list: 可选参数，可以设置为包含全部的外部函数的列表对象
    :param model: 可选参数，chat模型，默认模型为glm-4
    :return:
    """
    # 如果没有外部函数库，则执行普通的对话任务
    if function_list == None:
        response = client.chat.completions.create(model=model, messages=messages)
        response_message = response.choices[0].message
        final_resp = response_message.content
    else:
        # 创建functions对象
        tools = auto_functions(function_list)

        # 创建外部函数库字典
        available_functions = {func.__name__:func for func in function_list}

        # 第一次调用大模型
        response = client.chat.completions.create(model=model,
                                                  messages=messages,
                                                  tools=tools,
                                                  tool_choice="auto")
        response_message = response.choices[0].message
        tool_calls = response_message.tool_calls
        if tool_calls:
            ## GLM-4 Function Call的使用方式
            messages.append(response_message.model_dump())
            for tool_call in tool_calls:
                function_name = tool_call.function.name
                function_to_call = available_functions[function_name]
                function_args = json.loads(tool_call.function.arguments)
                ## 真正执行外部函数的就是这儿的代码
                function_response = function_to_call(**function_args)
                messages.append({"role":"tool",
                                 "content":function_response,
                                 "tool_call_id":tool_call.id})

            ## 第二次调用模型
            response = client.chat.completions.create(model=model,
                                                      messages=messages,
                                                      tools=tools)
            # 获取最终结果
            response_message = response.choices[0].message
            final_resp = response_message.content
        else:
            final_resp = response_message.content

    return final_resp

messages=[
    {"role": "system", "content": "你是一个邮件助手，帮我查询各种邮件信息"},
    {"role": "user", "content": "帮我查询一下，我最近的3封邮件内容"}
]

response = run_conversation(messages,function_list,"glm-4")
print(response)



